package com.softaria.spkiller.metadata.extractor;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import com.softaria.spkiller.metadata.ClassIdentifier;

public class InputStreamProviderImpl implements InputStreamProvider {

	private static final String[] ZIP_FILE_TYPES = new String[] { ".zip",
			".jar" };

	private String[] pathesToFoldersOrJars;
	
	private Collection<ZipFile> zipFiles = new ArrayList<ZipFile>();

	public InputStreamProviderImpl(String[] pathesToFoldersOrJars) throws ZipException, IOException {
		this.pathesToFoldersOrJars = pathesToFoldersOrJars;

		for (String path : pathesToFoldersOrJars) {
			File file = new File(path);

			processFile(file);
		}
	}

	private void processFile(File file) throws ZipException, IOException {
		if (file.isDirectory()) {
			File[] files = file.listFiles();

			for (File f : files) {
				processFile(f);
			}
		} else {
			if (isZipFile(file)) {
				zipFiles.add(new ZipFile(file));
			}
		}
	}

	private static boolean isZipFile(File file) {
		boolean result = false;
		String name = file.getName().toLowerCase();

		for (int i = 0; i < ZIP_FILE_TYPES.length; i++) {
			if (name.endsWith(ZIP_FILE_TYPES[i])) {
				result = true;
				break;
			}
		}
		return result;
	}

	@Override
	public InputStream getInputStream(ClassIdentifier id) throws IOException {
		String path = id.getPath();
		
		InputStream is = searchInFolders(path);
		
		if(is == null) {
			return searchInArchives(path);
		}
		else {
			return is;
		}
		
	}

	private InputStream searchInArchives(String path) throws IOException {
		for(ZipFile zf:zipFiles) {
			ZipEntry entry = zf.getEntry(path);
			if(entry != null) {
				return zf.getInputStream(entry);
			}
		}
		return null;
	}

	private InputStream searchInFolders(String path) throws FileNotFoundException {
		for(String p:pathesToFoldersOrJars) {
			File d = new File(p);
			if(d.isDirectory()) {
				File f = new File(d,path);
				if(f.exists()) {
					return new FileInputStream(f);
				}
			}
		}
		
		return null;
	}

}
